<?php

namespace hxhzyh\jwtAuth;

class Jwt
{
    private static $instance;

    private $secretKey = 'star';
    private $guard = '';

    public const ALG_METHOD_AES = 'AES';
    public const ALG_METHOD_HMACSHA256 = 'HMACSHA256';
    public const ALG_METHOD_HS256 = 'HS256';

    public static function getInstance(): self
    {
        if (!isset(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    public function publish(): JwtObject
    {
        return new JwtObject(['secretKey' => $this->guard . $this->secretKey]);
    }

    public function setSecretKey(string $key): self
    {
        $this->secretKey = $key;
        return $this;
    }

    public function setGuard(string $guard = ''): self
    {
        $this->guard = $guard;
        return $this;
    }

    public function decode(?string $raw): ?JwtObject
    {
        $items = explode('.', $raw);

        // token格式
        if (count($items) !== 3) {
            throw new \Exception('Token format error!');
        }

        // 验证header
        $header = Encryption::base64UrlDecode($items[0]);
        $header = json_decode($header, true);
        if (empty($header)) {
            throw new \Exception('Token header is empty!');
        }

        // 验证payload
        $payload = Encryption::base64UrlDecode($items[1]);
        $payload = json_decode($payload, true);
        if (empty($payload)) {
            throw new \Exception('Token payload is empty!');
        }

        if (empty($items[2])) {
            throw new \Exception('signature is empty');
        }

        $jwtObjConfig = array_merge(
            $header,
            $payload,
            [
                'signature' => $items[2],
                'secretKey' => $this->guard . $this->secretKey
            ]
        );

        return new JwtObject($jwtObjConfig);
    }
}